package com.xyd.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyd.auth.mapper.SysMenuMapper;
import com.xyd.auth.mapper.SysRoleMenuMapper;
import com.xyd.auth.service.ISysMenuService;
import com.xyd.auth.utils.MenuHelper;
import com.xyd.common.exception.YiYunGlobalException;
import com.xyd.model.system.SysMenu;
import com.xyd.model.system.SysRoleMenu;
import com.xyd.model.system.vo.AssignMenuVO;
import com.xyd.model.system.vo.MetaVO;
import com.xyd.model.system.vo.RouterVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.awt.*;
import java.sql.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper,SysMenu> implements ISysMenuService {

    @Autowired
    SysMenuMapper sysMenuMapper;
    @Autowired
    SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 获取菜单树型数据
     * @return
     */
    @Override
    public List<SysMenu> findNodes() {
        // 所有的菜单列表
        List<SysMenu> list =this.list();
        if (CollectionUtils.isEmpty(list)) return null;
        // 构建树形数据
        List<SysMenu> sysMenus = MenuHelper.buildTree(list);
        return sysMenus;
    }

    /**
     * 根据id删除菜单
     * 删除业务：
     *  1.被删除的菜单必须没有子菜单
     * @param id 要删除的菜单id
     * @return
     */
    @Override
    public void deleteById(Long id) {
        long count = this.count(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id));
        if (count > 0) {
            throw new YiYunGlobalException(40004,"该菜单还有子菜单，不能删除");
        }
        sysMenuMapper.deleteById(id);
    }

    /**
     * 根据角色的id 返回对应的菜单列表
     * @param roleId
     * @return
     */
    @Override
    public List<SysMenu> findSysMenuByRoleId(Long roleId) {
        // 全部菜单列表
        List<SysMenu> list =
                this.list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));

        // 根据角色id获取当前该角色已有的菜单
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        // 将角色菜单对象中的菜单ids封装到list集合中
        List<Long> menuIds = sysRoleMenus.stream().map(item -> item.getMenuId()).collect(Collectors.toList());
        // 遍历所有的菜单与角色已经拥有的菜单id比较
        list.forEach(permission -> {
            if(menuIds.contains(permission.getId())){
                // isSelect 属性用于判断是否为当前角色所有用的菜单。
                // 如果遍历的菜单对象和用户选中的菜单集中存在则修改isSelect属性为true
               permission.setSelect(true);
            }else{
                // 如果遍历的菜单对象和用户选中的菜单集中‘不存在则修改isSelect属性为false
                permission.setSelect(false);
            }
        });
        // 构建树型数据
        List<SysMenu> sysMenus = MenuHelper.buildTree(list);
        System.out.println(sysMenus);
        return sysMenus;
    }

    /**
     * 角色分配菜单
     * @param assignMenuVO
     */
    @Override
    public void doAssign(AssignMenuVO assignMenuVO) {
        // 删除已有的菜单
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId,assignMenuVO.getRoleId()));
        // 遍历assignMenuVO的要添加的菜单列表
        for(Long menuId: assignMenuVO.getMenuIdList()){
            if(StringUtils.isEmpty(menuId)) continue;
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(assignMenuVO.getRoleId());
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenuMapper.insert(sysRoleMenu);
        }
    }
    // 根据用户id查询菜单列表
    @Override
    public List<RouterVO> findSysMenuByUserId(Long userId) {
        // 用于构建router结构的菜单集合
        List<SysMenu> sysMenusList = new ArrayList<>();

        if(userId == 1){// 判断是否为超级用户管理员 == 1说明是
            sysMenusList = this.list( // 条件1： 状态为正常
                    new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1)
                            // 条件2：按照sortValue升序排列
                            .orderByAsc(SysMenu::getSortValue));
        }else{
            // 1.2 如果不是管理员 根据userId查询可以操作的菜单列表
            // 多表关联查询 ：用户角色关系表 角色菜单关系表 菜单表
            sysMenusList = baseMapper.findMenuListByUserId(userId);
        }
        // 将查询结果构建为树型数据
        List<SysMenu> sysMenusTree = MenuHelper.buildTree(sysMenusList);
        // 将树型数据构建成前端的router形式的数据
        List<RouterVO> routerVOList = this.buildeRouter(sysMenusTree);
        return routerVOList;
    }
//    把使用菜单操作工具类构建成的树形结构需要转变为框架要求的路由结
//    构。
    private List<RouterVO> buildeRouter(List<SysMenu> sysMenusTree) {
        ArrayList<RouterVO> routerVOS = new ArrayList<>();
        sysMenusTree.stream().forEach(sysMenu -> {
            RouterVO routerVO = new RouterVO();
            routerVO.setHidden(false);
            routerVO.setAlwaysShow(false);
            // 使用了一个自定义的方法 getRouterPath(sysMenu)
            routerVO.setPath(this.getRouterPath(sysMenu));
            routerVO.setComponent(sysMenu.getComponent());
            routerVO.setMeta(new MetaVO(sysMenu.getName(),sysMenu.getIcon()));
            // 下一层数据部分
            List<SysMenu> children = sysMenu.getChildren();
            // 分配权限的type也是2 但是他有path component 隐藏路由
            //type=1说明是二级菜单，在系统管理下面，比如用户管理\角色管理\菜单管理
            if(sysMenu.getType() == 1){ // 二级菜单
                // 首先加载出隐藏路由
                // type = 2 component不为空
                List<SysMenu> hiddenMenuList = children.stream().filter(item ->
                        !StringUtils.isEmpty(item.getComponent())).collect(Collectors.toList());
                hiddenMenuList.stream().forEach(hiddenMenu -> {
                    RouterVO hiddenRouterVO = new RouterVO();
                    hiddenRouterVO.setHidden(true);
                    hiddenRouterVO.setAlwaysShow(false);
                    hiddenRouterVO.setPath(this.getRouterPath(hiddenMenu));
                    hiddenRouterVO.setComponent(hiddenMenu.getComponent());
                    hiddenRouterVO.setMeta(new MetaVO(sysMenu.getName(),sysMenu.getIcon()));
                    routerVOS.add(hiddenRouterVO);
                });
            }else { //说明sysMenu不是二级菜单，应该是一级菜单
               if(!CollectionUtils.isEmpty(children)){
                    // 有子菜单
                   routerVO.setAlwaysShow(true);
               }
               routerVO.setChildren(buildeRouter(children));
            }
            routerVOS.add(routerVO);
        });
        return routerVOS;
    }
    /**获取路由地址
     * @param sysMenu 菜单信息
     * @return 路由地址
     */
    private String getRouterPath(SysMenu sysMenu) {
        // 主路由 加 ‘/’
        String path ="/"+ sysMenu.getPath();
        // 子路由 没有 ‘/’
        if(sysMenu.getParentId() != 0){
            path =sysMenu.getPath();
        }
        return path;
    }
    // 根据用户的id查询可以操作的按钮
    @Override
    public List<String> findSysUserPermsByUserId(Long userId) {
        List<SysMenu> sysMenus = new ArrayList<>();
        // 1 判断当前用户是否是管理员 userID = 1
        if(userId == 1){ // 管理员将所有的菜单全获取到
           sysMenus = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
        }else{ // 非管理员
            sysMenus = baseMapper.findMenuListByUserId(userId);
        }
        // 2 从查询出来的数据里面，获取可以操作的按钮的list集合（perms）
        List<String> permsList = sysMenus.stream()
                .filter(item -> item.getType() == 2) // 过滤器 类型是按钮 type = 2
                .map(SysMenu::getPerms).collect(Collectors.toList());

        return permsList;
    }
}
